﻿using BCCommon;
using BCCommon.TMS.FreightEnums;
using BCData.Common.Area;
using BCData.TMS.Agent.AgentAreaRecord;
using BCData.TMS.HorsemanFreightExtention;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.HorsemanFreightExtention;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.HorsemanFreightExtention;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace BCService.TMS.HorsemanFreightExtention
{
    public class HorsemanFreightExtentionService : IHorsemanFreightExtentionService
    {
        private readonly IHorsemanFreightExtentionData horsemanFreightExtentionData;
        private readonly ICountyData countyData;
        private readonly IRedisService redisService;
        private readonly string key = string.Format("{0}", EntityNameConst.HorsemanFreightExtentionEntity);
        private readonly IAgentAreaRecordData agentAreaRecordData;
        private readonly IDatabaseContext databaseContext;

        public HorsemanFreightExtentionService(IHorsemanFreightExtentionData horsemanFreightExtentionData, ICountyData countyData, IRedisService redisService, IAgentAreaRecordData agentAreaRecordData, IDatabaseContext databaseContext)
        {
            this.horsemanFreightExtentionData = horsemanFreightExtentionData;
            this.countyData = countyData;
            this.redisService = redisService;
            this.agentAreaRecordData = agentAreaRecordData;
            this.databaseContext = databaseContext;
        }

        public int Add(AdminDto admin, HorsemanFreightExtentionRequestDto dto)
        {
            List<HorsemanFreightExtentionEntity> entities = new List<HorsemanFreightExtentionEntity>();
            if (admin.AgentRecord != null)
            {
                if (!dto.CountyCodes.Any())
                {
                    throw new ArgumentException("代理商身份设置运费，区县信息不能为空。");
                }
                foreach (var item in dto.CountyCodes)
                {
                    var county = this.countyData.GetCounty(item);
                    if (county == null)
                    {
                        throw new ArgumentException("区县信息不存在。");
                    }
                    var agentAreaRecord = this.agentAreaRecordData.GetByAgentRecordIdAndCountyCode(admin.AgentRecord.AgentRecordId, item).GetAwaiter().GetResult();
                    if (agentAreaRecord != null)
                    {
                        throw new ArgumentException($"该区县 {item} 无权限设置。");
                    }
                }
            }
            else
            {
                if (dto.CountyCodes.Any())
                {
                    foreach (var item in dto.CountyCodes)
                    {
                        var county = this.countyData.GetCounty(item);
                        if (county == null)
                        {
                            throw new ArgumentException("区县信息不存在。");
                        }

                    }
                }
            }
            if (dto.FreightExtentionType == HorsemanFreightExtentionType.Distance)
            {
                if (!dto.HorsemanFreightDistanceStages.Any())
                {
                    throw new ArgumentException("距离运费阶梯信息不能为空!");
                }
                foreach (var item in dto.HorsemanFreightDistanceStages)
                {
                    if (!item.MaxEachDistance.HasValue || (item.MaxEachDistance.HasValue && item.MaxEachDistance.Value <= 0))
                    {
                        throw new ArgumentException("距离模式下，最大里程为必填项!");
                    }
                    if (!item.EachDistancePrice.HasValue || (item.EachDistancePrice.HasValue && item.EachDistancePrice.Value <= 0))
                    {
                        throw new ArgumentException("距离模式下，单公里价格为必填项!");
                    }
                    if (!item.NightEachDistancePrice.HasValue || (item.NightEachDistancePrice.HasValue && item.NightEachDistancePrice.Value <= 0))
                    {
                        throw new ArgumentException("距离模式下，夜间单公里价格为必填项!");
                    }

                    if (dto.HorsemanFreightWeightStages.GroupBy(s => s.MaxEachWeight).Count(m => m.Count() > 1) >= 1)
                    {
                        throw new ArgumentException("相同的里程不能同时存在一个阶梯内");
                    }
                    if (dto.CountyCodes.Any())
                    {
                        foreach (var countyCode in dto.CountyCodes.Distinct())
                        {
                            var county = this.countyData.GetCounty(countyCode);
                            entities.Add(new HorsemanFreightExtentionEntity
                            {
                                FreightExtentionType = dto.FreightExtentionType.ToString(),
                                IsBase = dto.IsBase,
                                CountyCode = county.CountyCode,
                                CountyId = county.CountyId,
                                MaxEachDistance = item.MaxEachDistance.Value,
                                EachDistancePrice = item.EachDistancePrice.Value,
                                NightEachDistancePrice = item.NightEachDistancePrice.Value
                            });
                        }
                    }
                    else
                    {
                        entities.Add(new HorsemanFreightExtentionEntity
                        {
                            FreightExtentionType = dto.FreightExtentionType.ToString(),
                            IsBase = dto.IsBase,
                            MaxEachDistance = item.MaxEachDistance.Value,
                            EachDistancePrice = item.EachDistancePrice.Value,
                            NightEachDistancePrice = item.NightEachDistancePrice.Value
                        });
                    }
                }

            }
            else
            {
                if (!dto.HorsemanFreightWeightStages.Any())
                {
                    throw new ArgumentException("重量运费阶梯信息不能为空!");
                }
                foreach (var item in dto.HorsemanFreightWeightStages)
                {
                    if (!item.MaxEachWeight.HasValue || (item.MaxEachWeight.HasValue && item.MaxEachWeight.Value <= 0))
                    {
                        throw new ArgumentException("重量模式下，最大重量为必填项!");
                    }
                    if (!item.EachWeightPrice.HasValue || (item.EachWeightPrice.HasValue && item.EachWeightPrice.Value <= 0))
                    {
                        throw new ArgumentException("重量模式下，单公斤价格为必填项!");
                    }
                    if (!item.NightEachWeightPrice.HasValue || (item.NightEachWeightPrice.HasValue && item.NightEachWeightPrice.Value <= 0))
                    {
                        throw new ArgumentException("重量模式下，夜间单公斤价格为必填项!");
                    }
                    if (dto.HorsemanFreightWeightStages.GroupBy(s => s.MaxEachWeight).Count(m => m.Count() > 1) >= 1)
                    {
                        throw new ArgumentException("相同的续重不能同时存在一个阶梯内");
                    }
                    if (dto.CountyCodes.Any())
                    {
                        foreach (var countyCode in dto.CountyCodes.Distinct())
                        {
                            var county = this.countyData.GetCounty(countyCode);
                            entities.Add(new HorsemanFreightExtentionEntity
                            {
                                FreightExtentionType = dto.FreightExtentionType.ToString(),
                                IsBase = dto.IsBase,
                                CountyCode = county.CountyCode,
                                CountyId = county.CountyId,
                                MaxEachWeight = item.MaxEachWeight.Value,
                                EachWeightPrice = item.EachWeightPrice.Value,
                                NightEachWeightPrice = item.NightEachWeightPrice.Value
                            });
                        }
                    }
                    else
                    {
                        entities.Add(new HorsemanFreightExtentionEntity
                        {
                            FreightExtentionType = dto.FreightExtentionType.ToString(),
                            IsBase = dto.IsBase,
                            MaxEachWeight = item.MaxEachWeight.Value,
                            EachWeightPrice = item.EachWeightPrice.Value,
                            NightEachWeightPrice = item.NightEachWeightPrice.Value
                        });
                    }
                }
            }
            var result = horsemanFreightExtentionData.InserAllAsync(entities).GetAwaiter().GetResult();
            if (result <= 0)
            {
                throw new ArgumentException("运费扩展信息新增失败。");
            }
            return result;
        }

        public bool BatchUpdate(AdminDto admin, string countyCode, HorsemanFreightExtentionBatchPutDto dto)
        {
            if (countyCode.Length > 6)
            {
                throw new ArgumentException("区县编码长度应该6位。");
            }
            Regex regex = new Regex(RegexPatterns.NUMBER);
            if (!regex.IsMatch(countyCode))
            {
                throw new ArgumentException("区县编码应全部是数字。");
            }
            if (!this.countyData.CheckExistsByCode(countyCode))
            {
                throw new ArgumentException("区县信息不存在。");
            }
            var data = this.horsemanFreightExtentionData.GetListByCountyCodeAsync(countyCode).GetAwaiter().GetResult();
            if (!data.Any())
            {
                throw new ArgumentException("该区县不存在运费阶梯信息。");
            }
            List<HorsemanFreightExtentionEntity> entities = new List<HorsemanFreightExtentionEntity>();

            if (dto.FreightExtentionType == HorsemanFreightExtentionType.Distance)
            {
                if (!dto.HorsemanFreightDistanceStages.Any())
                {
                    throw new ArgumentException("距离运费阶梯信息不能为空!");
                }
                foreach (var item in dto.HorsemanFreightDistanceStages)
                {
                    if (!item.MaxEachDistance.HasValue || (item.MaxEachDistance.HasValue && item.MaxEachDistance.Value <= 0))
                    {
                        throw new ArgumentException("距离模式下，最大里程为必填项!");
                    }
                    if (!item.EachDistancePrice.HasValue || (item.EachDistancePrice.HasValue && item.EachDistancePrice.Value <= 0))
                    {
                        throw new ArgumentException("距离模式下，单公里价格为必填项!");
                    }
                    if (!item.NightEachDistancePrice.HasValue || (item.NightEachDistancePrice.HasValue && item.NightEachDistancePrice.Value <= 0))
                    {
                        throw new ArgumentException("距离模式下，夜间单公里价格为必填项!");
                    }
                    entities.Add(new HorsemanFreightExtentionEntity
                    {
                        FreightExtentionType = dto.FreightExtentionType.ToString(),
                        IsBase = dto.IsBase,
                        CountyCode = data.First().CountyCode,
                        CountyId = data.First().CountyId,
                        MaxEachDistance = item.MaxEachDistance.Value,
                        EachDistancePrice = item.EachDistancePrice.Value,
                        NightEachDistancePrice = item.NightEachDistancePrice.Value
                    });
                }
                if (dto.HorsemanFreightWeightStages.GroupBy(s => s.MaxEachWeight).Count(m => m.Count() > 1) >= 1)
                {
                    throw new ArgumentException("相同的里程不能同时存在一个阶梯内");
                }
            }
            else
            {
                if (!dto.HorsemanFreightWeightStages.Any())
                {
                    throw new ArgumentException("重量运费阶梯信息不能为空!");
                }
                foreach (var item in dto.HorsemanFreightWeightStages)
                {
                    if (!item.MaxEachWeight.HasValue || (item.MaxEachWeight.HasValue && item.MaxEachWeight.Value <= 0))
                    {
                        throw new ArgumentException("重量模式下，最大重量为必填项!");
                    }
                    if (!item.EachWeightPrice.HasValue || (item.EachWeightPrice.HasValue && item.EachWeightPrice.Value <= 0))
                    {
                        throw new ArgumentException("重量模式下，单公斤价格为必填项!");
                    }
                    if (!item.NightEachWeightPrice.HasValue || (item.NightEachWeightPrice.HasValue && item.NightEachWeightPrice.Value <= 0))
                    {
                        throw new ArgumentException("重量模式下，夜间单公斤价格为必填项!");
                    }
                    entities.Add(new HorsemanFreightExtentionEntity
                    {
                        FreightExtentionType = dto.FreightExtentionType.ToString(),
                        IsBase = dto.IsBase,
                        CountyCode = data.First().CountyCode,
                        CountyId = data.First().CountyId,
                        MaxEachWeight = item.MaxEachWeight.Value,
                        EachWeightPrice = item.EachWeightPrice.Value,
                        NightEachWeightPrice = item.NightEachWeightPrice.Value
                    });
                }
                if (dto.HorsemanFreightWeightStages.GroupBy(s => s.MaxEachWeight).Count(m => m.Count() > 1) >= 1)
                {
                    throw new ArgumentException("相同的续重不能同时存在一个阶梯内");
                }
            }
            this.databaseContext.BeginTransaction();
            var result = horsemanFreightExtentionData.UpdateAllAsync(countyCode, entities).GetAwaiter().GetResult();
            if (!result)
            {
                throw new ArgumentException("运费扩展信息修改失败。");
            }
            this.databaseContext.Commit();
            return result;
        }

        public HorsemanFreightExtentionDto GetByHorsemanFreightExtentionIdId(long horsemanFreightExtentionId)
        {
            string cacheKey = this.redisService.GetKey(key, horsemanFreightExtentionId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.horsemanFreightExtentionData.GetByHorsemanFreightExtentionIdAsync(horsemanFreightExtentionId).GetAwaiter().GetResult();
                if (data == null)
                {
                    throw new ArgumentException("运费扩展信息不存在。");
                }
                return data.As<HorsemanFreightExtentionDto>();
            }, TimeSpan.FromDays(30));
            return result;
        }

        public PageableList<HorsemanFreightExtentionViewDto> GetList(AdminDto admin, bool? isBase, string countyCode, HorsemanFreightExtentionType? freightExtentionType, bool? ascending, string sortName, int pageIndex, int pageSize)
        {
            PageableList<HorsemanFreightExtentionViewDto> result = new PageableList<HorsemanFreightExtentionViewDto>();
            List<string> countyCodes = new List<string>();
            if (!string.IsNullOrWhiteSpace(countyCode))
            {
                countyCodes.Add(countyCode);
            }
            //代理商先查询，如果没查到返回总部数据
            if (admin.AgentRecord != null)
            {
                var agentAreaRecords = this.agentAreaRecordData.GetByAgentRecordId(admin.AgentRecord.AgentRecordId).GetAwaiter().GetResult();
                countyCodes.AddRange(agentAreaRecords.Select(s => s.CountyCode));
                var queryResult = this.horsemanFreightExtentionData.GetListAsync(isBase, countyCodes, freightExtentionType, ascending, sortName, pageIndex, pageSize).GetAwaiter().GetResult();
                if (queryResult.Item1.Any())
                {
                    result = new PageableList<HorsemanFreightExtentionViewDto>
                    {
                        Items = queryResult.Item1.As<IEnumerable<HorsemanFreightExtentionViewDto>>(),
                        Count = queryResult.Item2,
                        PageIndex = pageIndex,
                        PageSize = pageSize
                    };
                }
                else
                {
                    var data = this.horsemanFreightExtentionData.GetListAsync(true, countyCodes, freightExtentionType, ascending, sortName, pageIndex, pageSize).GetAwaiter().GetResult();
                    result = new PageableList<HorsemanFreightExtentionViewDto>
                    {
                        Items = data.Item1.As<IEnumerable<HorsemanFreightExtentionViewDto>>(),
                        Count = data.Item2,
                        PageIndex = pageIndex,
                        PageSize = pageSize
                    };
                }
            }
            else
            {
                var queryResult = this.horsemanFreightExtentionData.GetListAsync(isBase, countyCodes, freightExtentionType, ascending, sortName, pageIndex, pageSize).GetAwaiter().GetResult();
                if (queryResult.Item1.Any())
                {
                    result = new PageableList<HorsemanFreightExtentionViewDto>
                    {
                        Items = queryResult.Item1.As<IEnumerable<HorsemanFreightExtentionViewDto>>(),
                        Count = queryResult.Item2,
                        PageIndex = pageIndex,
                        PageSize = pageSize
                    };
                }
            }
            return result;
        }

        public IEnumerable<HorsemanFreightExtentionDto> GetListByCountyCode(string countyCode)
        {
            if (string.IsNullOrWhiteSpace(countyCode))
            {
                string cacheKey = string.Format("{0}:IsBase={1}",key, true);
                var result = this.redisService.TryGet(cacheKey, () =>
                {
                    var data = this.horsemanFreightExtentionData.GetListAsync().GetAwaiter().GetResult();
                    return data.As<IEnumerable<HorsemanFreightExtentionDto>>();
                }, TimeSpan.FromDays(30));
                return result;
            }
            else
            {
                string cacheKey = this.redisService.GetKey(key, countyCode);
                var result = this.redisService.TryGet(cacheKey, () =>
                {
                    var data = this.horsemanFreightExtentionData.GetListByCountyCodeAsync(countyCode).GetAwaiter().GetResult();
                    return data.As<IEnumerable<HorsemanFreightExtentionDto>>();
                }, TimeSpan.FromDays(30));
                return result;
            }
        }

        public HorsemanFreightExtentionDto Update(long horsemanFreightExtentionId, HorsemanFreightExtentionPutDto dto)
        {
            var oldEntity = this.horsemanFreightExtentionData.GetByHorsemanFreightExtentionIdAsync(horsemanFreightExtentionId).GetAwaiter().GetResult();
            if (oldEntity == null)
            {
                throw new ArgumentException("此运费配置信息不存在!");
            }
            if (dto.CountyId.HasValue)
            {
                if (!this.countyData.CheckExistsById(dto.CountyId.Value))
                {
                    throw new ArgumentException("区县信息不存在。");
                }
                if (string.IsNullOrWhiteSpace(dto.CountyCode))
                {
                    throw new ArgumentException("区县编码不能为空。");
                }
                if (dto.CountyCode.Length > 6)
                {
                    throw new ArgumentException("区县编码长度应该6位。");
                }
                Regex regex = new Regex(RegexPatterns.NUMBER);
                if (!regex.IsMatch(dto.CountyCode))
                {
                    throw new ArgumentException("区县编码应全部是数字。");
                }
            }
            if (dto.FreightExtentionType == HorsemanFreightExtentionType.Distance)
            {
                if (!dto.MaxEachDistance.HasValue || (dto.MaxEachDistance.HasValue && dto.MaxEachDistance.Value <= 0))
                {
                    throw new ArgumentException("距离模式下，最大里程为必填项!");
                }
                if (!dto.EachDistancePrice.HasValue || (dto.EachDistancePrice.HasValue && dto.EachDistancePrice.Value <= 0))
                {
                    throw new ArgumentException("距离模式下，单公里价格为必填项!");
                }
                if (!dto.NightEachDistancePrice.HasValue || (dto.NightEachDistancePrice.HasValue && dto.NightEachDistancePrice.Value <= 0))
                {
                    throw new ArgumentException("距离模式下，夜间单公里价格为必填项!");
                }
            }
            else
            {
                if (!dto.MaxEachWeight.HasValue || (dto.MaxEachWeight.HasValue && dto.MaxEachWeight.Value <= 0))
                {
                    throw new ArgumentException("重量模式下，最大重量为必填项!");
                }
                if (!dto.EachWeightPrice.HasValue || (dto.EachWeightPrice.HasValue && dto.EachWeightPrice.Value <= 0))
                {
                    throw new ArgumentException("重量模式下，单公斤价格为必填项!");
                }
                if (!dto.NightEachWeightPrice.HasValue || (dto.NightEachWeightPrice.HasValue && dto.NightEachWeightPrice.Value <= 0))
                {
                    throw new ArgumentException("重量模式下，夜间单公斤价格为必填项!");
                }
            }
            var entity = dto.As<HorsemanFreightExtentionEntity>();
            entity.HorsemanFreightExtentionId = horsemanFreightExtentionId;
            var result = horsemanFreightExtentionData.UpdateAsync(entity).GetAwaiter().GetResult();
            if (result == null)
            {
                throw new ArgumentException("运费扩展信息更新失败。");
            }
            string cacheKey = this.redisService.GetKey(key, horsemanFreightExtentionId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            return result.As<HorsemanFreightExtentionDto>();
        }
    }
}
